using System;

namespace PDUConverter
{
    /// <summary>
    /// Represents an outgoing SMS PDU.
    /// </summary>
    public abstract class OutgoingSmsPdu : SmsPdu
    {
        protected OutgoingMessageFlags messageFlags;
        protected byte messageReference = 0;
        private const byte TP_MTI_SMS_Command = 2;
        private const byte TP_MTI_SMS_Deliver_Report = 0;
        private const byte TP_MTI_SMS_Submit = 1;

        protected OutgoingSmsPdu()
        {
        }

        /// <summary>
        /// Decodes an outgoing SMS PDU stream.
        /// </summary>
        /// <param name="pdu">The PDU string to decode.</param>
        /// <param name="includesSmscData">Specify true if the PDU data contains an SMSC header, otherwise false.</param>
        /// <returns>An <see cref="T:GsmComm.PduConverter.OutgoingSmsPdu" /> object representing the decoded message.</returns>
        /// <remarks>Use this method when the actual length of the message is not known.</remarks>
        public static OutgoingSmsPdu Decode(string pdu, bool includesSmscData)
        {
            return Decode(pdu, includesSmscData, -1);
        }

        /// <summary>
        /// Decodes an outgoing SMS PDU stream.
        /// </summary>
        /// <param name="pdu">The PDU string to decode</param>
        /// <param name="includesSmscData">Specify true if the PDU data contains an SMSC header, otherwise false.</param>
        /// <param name="actualLength">The length of the PDU in bytes, not including the SMSC header.</param>
        /// <returns>An <see cref="T:GsmComm.PduConverter.OutgoingSmsPdu" /> object representing the decoded message.</returns>
        public static OutgoingSmsPdu Decode(string pdu, bool includesSmscData, int actualLength)
        {
            if (pdu == string.Empty)
            {
                throw new ArgumentException("pdu must not be an empty string.");
            }
            int num = 0;
            if (includesSmscData)
            {
                byte @byte = BcdWorker.GetByte(pdu, num++);
                if (@byte > 0)
                {
                    num += @byte;
                }
            }
            OutgoingMessageType messageType = GetMessageType(BcdWorker.GetByte(pdu, num++));
            switch (messageType)
            {
                case OutgoingMessageType.SmsSubmit:
                    throw new NotSupportedException("Message type " + messageType.ToString() + " recognized, but not supported by the SMS decoder.");
            }
            return new SmsSubmitPdu(pdu, includesSmscData, actualLength);
        }

        private static OutgoingMessageType GetMessageType(byte flags)
        {
            byte num = (byte) (((((flags & 2) > 0) ? 1 : 0) * 2) + (flags & 1));
            switch (num)
            {
                case 0:
                    return OutgoingMessageType.SmsDeliverReport;

                case 1:
                    return OutgoingMessageType.SmsSubmit;

                case 2:
                    return OutgoingMessageType.SmsCommand;
            }
            throw new ArgumentException("Unknown message type " + num.ToString() + " (flags=" + flags.ToString() + ")", "flags");
        }

        /// <summary>
        /// Gets or sets the message reference.
        /// </summary>
        /// <remarks><para>Represents the TP-Message-Reference octet of the PDU.</para>
        /// <para>Normally there is no need to change this property because
        /// the reference is set by the sending device.</para>.
        /// </remarks>
        public byte MessageReference
        {
            get
            {
                return this.messageReference;
            }
            set
            {
                this.messageReference = value;
            }
        }

        /// <summary>
        /// Gets the message type.
        /// </summary>
        public OutgoingMessageType MessageType
        {
            get
            {
                return this.messageFlags.MessageType;
            }
        }
    }
}